package com.xtm.exercise.base.A12threadDemo.CompletableFuture;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.xtm.exercise.base.A08Collection.A02set.Person;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;


import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 类描述：带参数异步线程，返回值
 *         线程池-异步编排
 *         runXxx       :  没有返回结果的
 *         supplyAsync  :  可以获取返回结果的
 *
 * @author lei
 * @version 1.0
 * @date 2023/3/5 22:32
 */
public class CompletableFutureDemo {


    //定义线程池
    public static ExecutorService executor = new ThreadPoolExecutor(
            3,
            6,
            30,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(20),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Person person = new Person();
        person.setName("wanglei");

        //定义线程池
//        ExecutorService threadPool = new ThreadPoolExecutor(
//                3,
//                6,
//                30,
//                TimeUnit.SECONDS,
//                new LinkedBlockingQueue<>(20),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.DiscardPolicy());


        CompletableFuture<List<Person>> personComplete = CompletableFuture.supplyAsync(() -> {

            List<Person> personList = findInvoiceLedger(person);

            return personList;
        });

        person.setAge(12);

        System.out.println(person.toString());

        CompletableFuture.runAsync(() -> {

            List<Person> personList = findInvoiceLedger(person);

        });

    }

    public static List<Person> findInvoiceLedger(Person person) {
        person.setAge(19);
        List<Person> resultAll =new ArrayList<>();
        resultAll.add(person);
        return resultAll;
    }

    /**
     * 线程方法执行后的处理   handle
     */
    @Test
    public void test0(){
        Person person = new Person();
        person.setName("wanglei");

        //定义线程池
//        ExecutorService threadPool = new ThreadPoolExecutor(
//                3,
//                6,
//                30,
//                TimeUnit.SECONDS,
//                new LinkedBlockingQueue<>(20),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.DiscardPolicy());


        CompletableFuture<List<Person>> personComplete = CompletableFuture.supplyAsync(() -> {

            List<Person> personList = findInvoiceLedger(person);

            return personList;
        }, executor).handle((res,thr) -> {  // handle : 方法执行后的处理  可以对结果做最后的处理（可处理异常），可改变返回值
            // res:结果  thr：异常
            System.out.println("异步任务成功完成了...结果是：" +res + "异常是：" + thr);
            if (res != null ) {

                if(res.size() > 0){
                    for (int i = 0; i < res.size(); i++) {
                        Person ps = res.get(i);
                        ps.setName("改变后的值wanglei");
                    }
                }
                System.out.println(res);
                return res;
            }
            if (thr != null) {
                return res;
            }
            return res;
        });

        person.setAge(12);

        System.out.println(person.toString());

        CompletableFuture.runAsync(() -> {

            List<Person> personList = findInvoiceLedger(person);

        });
    }

    @Test
    public void test01() throws ExecutionException, InterruptedException {
        /**
         * 线程串行化，   接收上一个线程的结果，同时开启下一个线程
         * 1、thenRun:不能获取到上一步的执行结果，无返回值
         * .thenRunAsync(() ->{
         *             System.out.println("任务2启动了....");
         *         },executor);
         * 2、能接受上一步结果，但是无返回值 thenAcceptAsync
         * 3、thenApplyAsync 能收受上一步结果，有返回值
         *
         */

        //定义线程池
//        ExecutorService threadPool = new ThreadPoolExecutor(
//                3,
//                6,
//                30,
//                TimeUnit.SECONDS,
//                new LinkedBlockingQueue<>(20),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.DiscardPolicy());

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了..." + res);
            return "Hello " + res;
        }, executor);
        String s = future.get();

        System.out.println("main....stop....." + s);
    }

    @Test
    public void test03() throws ExecutionException, InterruptedException {

        /**
         * 两个都完成
         */

        //定义线程池
//        ExecutorService executor = new ThreadPoolExecutor(
//                3,
//                6,
//                30,
//                TimeUnit.SECONDS,
//                new LinkedBlockingQueue<>(20),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.DiscardPolicy());


        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1结束：" + i);
            return i;
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2当前线程：" + Thread.currentThread().getId());
            System.out.println("任务2结束：");
            return "Hello";
        }, executor);

        // f1 和 f2 执行完成后在执行这个
//        future01.runAfterBothAsync(future02,() -> {
//            System.out.println("任务3开始");
//        },executor);

        // 返回f1 和 f2 的运行结果
//        future01.thenAcceptBothAsync(future02,(f1,f2) -> {
//            System.out.println("任务3开始....之前的结果:" + f1 + "==>" + f2);
//        },executor);

        // f1 和 f2 单独定义返回结果
        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":" + f2 + "-> Haha";
        }, executor);

        System.out.println("main....end....." + future.get());
    }

    @Test
    public void test04(){
        /**
         * 两个任务，只要有一个完成，我们就执行任务
         * runAfterEnitherAsync：不感知结果，自己没有返回值
         * acceptEitherAsync：感知结果，自己没有返回值
         *  applyToEitherAsync：感知结果，自己有返回值
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1结束：" + i);
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2当前线程：" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束：");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        }, executor);

//        future01.runAfterEitherAsync(future02,() ->{
//            System.out.println("任务3开始...之前的结果:");
//        },executor);
//
//        future01.acceptEitherAsync(future02,(res) -> {
//            System.out.println("任务3开始...之前的结果:" + res);
//        },executor);

        CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
            System.out.println("任务3开始...之前的结果：" + res);
            return res.toString() + "->哈哈";
        }, executor);
    }

    @Test
    public void test05() throws ExecutionException, InterruptedException {
        /**
         * 多任务组合
         *      allOf：**等待所有任务完成**
         *      anyOf:**只要有一个任务完成**
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "hello.jpg";
        });

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256G";
        });

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("查询商品介绍");
            return "华为";
        });

        // 等待全部执行完
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
//        allOf.get();

        // 只需要有一个执行完
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        anyOf.get();
        System.out.println("main....end....." + anyOf.get());
    }

}
